package swym.server;

import java.util.*;
import swym.server.events.*;
import swym.server.file.FileAction;

public class Client
{
    private String name;
    private Vector<ClientConnection> clientConnections;
    private Vector<ClientListener> clientListeners;
    
    public Client( String name )
    {
        this.name   = name;
        
        clientConnections = new Vector<ClientConnection>();
        clientListeners = new Vector<ClientListener>();
    }
    
    public String getName() { return name; }
    public boolean isConnected() { return !clientConnections.isEmpty(); }
    public Vector<ClientConnection> getConnections() { return clientConnections; }
    
    public void setName( String name ) { this.name = name; }
    
    public void addConnection( ClientConnection connection )
    {
        boolean isFirst = false;
        
        synchronized ( clientConnections )
        {
            connection.setClient( this );
            clientConnections.add( connection );
            
            isFirst = ( clientConnections.size() == 1 );
        }
        
        invokeClientConnection( connection, isFirst );
    }
    
    public void closeConnection( ClientConnection connection )
    {
        synchronized ( clientConnections )
        {
            clientConnections.remove( connection );
        }
    }
    
    /**
     * Call this method when a new file action has 
     * occurred that the client should be aware of.
     * 
     * If there exists a proper client connection ready
     * to receive the notification of this new update, 
     * then add it to the connection's queue.
     * @param action
     */
    public void alertNewFileAction( FileAction action )
    {
        synchronized ( clientConnections )
        {
            for ( ClientConnection connection : clientConnections )
            {
                if ( connection.isUpdateConnection() )
                    connection.queueClientUpdate( action );
            }
        }
    }
    
    public String toString()
    {
        return "client: " + name + " with " + clientConnections.size() + " connections";
    }
    
    public void addClientListener( ClientListener listener )
    {
        if ( listener != null )
        {
            synchronized ( clientListeners )
            {
                clientListeners.add( listener );
            }
        }
        else
            throw new NullPointerException( "Client.addClientListener(): null listener" );
    }
    
    public void removeClientListener( ClientListener listener )
    {
        synchronized ( clientListeners )
        {
            clientListeners.remove( listener );
        }
    }
    
    private void invokeClientConnection( final ClientConnection connection, boolean isFirstConnection )
    {
        synchronized ( clientListeners )
        {
            for ( ClientListener listener : clientListeners )
                listener.handleNewConnection( connection, isFirstConnection );
        }
    }
}